package services.dingtalk


import java.sql.Timestamp
import java.time.{LocalDateTime, ZoneId}
import com.dingtalk.api.DefaultDingTalkClient
import com.dingtalk.api.request._
import com.dingtalk.api.response._
import com.taobao.api.ApiException
import models.users._

import javax.inject.{Inject, Singleton}
import play.api.cache.SyncCacheApi
import play.api.{Configuration, Logging}
import security.Encode

import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.util.Random

@Singleton
class DingtalkService @Inject()(config: Configuration,
                                usersRepo: UserGroupRepository,
                                cache: SyncCacheApi
                               )(implicit exec: ExecutionContext) extends Logging {
  val sec = security.Encode

  def getDingtalkConfig(com: String) = config.get[DingtalkConfig](com) // default

  //  val company = ComDingtalkService.companyNum(dtConfig(com).company)

  protected def getToken(company: String = "") = {
    def getTokenFromDingtalk(company: String = "") = {
      val client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken")
      val request = new OapiGettokenRequest
      val dingtalkConfig = getDingtalkConfig(company)
      request.setAppkey(dingtalkConfig.AppKey)
      request.setAppsecret(dingtalkConfig.AppSecret)
      request.setHttpMethod("GET")
      val response: OapiGettokenResponse = client.execute(request)
      logger.debug(s"def getTokenFromDingtalk($company)")
      if (response.getErrcode == 0) {
        cache.set(s"dingtalk.token.$company", response.getAccessToken, (response.getExpiresIn - 10).seconds)
        response.getAccessToken
      } else {
        ""
      }
    }
    cache.getOrElseUpdate[String](s"dingtalk.token.$company") {
      getTokenFromDingtalk(company)
    }
  }

  def getPartment(company: String) = {
      val client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list")
      val req = new OapiDepartmentListRequest
      req.setHttpMethod("GET")
      val rsp = client.execute(req, getToken(company))
      if (rsp.getErrcode == 0) Option(rsp.getDepartment)
      else {
        rsp.getErrmsg;
        None
      }
  }

  def getDeptMember(company: String, depId: String) = {
    Thread.sleep(100)
    val client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getDeptMember")
    val req = new OapiUserGetDeptMemberRequest
    req.setDeptId(depId)
    req.setHttpMethod("GET")
    client.execute(req, getToken(company))
  }

  def getUser(company: String, userID: String) = {
    Thread.sleep(100)
    try {
      val client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get")
      val req = new OapiUserGetRequest
      req.setUserid(userID)
      req.setHttpMethod("GET")
      val res = client.execute(req, getToken(company))
      logger.debug(s"getUser:${res.getBody}")
      usersRepo.userCreateUpdate(
        User(
          id = None,
          company = DingtalkService.companyNum(getDingtalkConfig(company).company),
          password = sec.pwdHashed(res.getUnionid + Random.nextFloat().toString),
          username = res.getName,
          position = Option(res.getPosition),
          email = Option(res.getEmail),
          is_active = true,
          userid = res.getUserid,
          unionid = res.getUnionid,
          tel = Option(res.getTel),
          workPlace = Option(res.getWorkPlace),
          remark = Option(res.getRemark),
          mobile = res.getMobile,
          orgEmail = Option(res.getOrgEmail),
          isLeaderInDepts = Option(res.getIsLeaderInDepts),
          department = res.getDepartment.toArray().mkString(","),
          avatar = Option(res.getAvatar),
          hiredDate = if (res.getHiredDate == null) Timestamp.valueOf(LocalDateTime.now()) else Timestamp.valueOf(res.getHiredDate.toInstant.atZone(ZoneId.systemDefault()).toLocalDateTime),
          jobnumber = Option(res.getJobnumber),
          extattr = Option(res.getExtattr),
          lastLoginDate = None
        ))
      //      System.out.println(res.getBody)
      Option(req)
    } catch {
      case e: ApiException => {
        logger.warn("getUser", e)
        None
      }
    }
  }

  def getUserInfo(company: String, requestAuthCode: String) = {
    val client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo")
    val request = new OapiUserGetuserinfoRequest
    request.setCode(requestAuthCode)
    request.setHttpMethod("GET")
    val response = client.execute(request, getToken(company))
    logger.debug(s"${response.getBody}")
    response.getUserid
  }

  def groupCreate(group: Group) = usersRepo.groupCreate(Group(id = group.id, parentid = group.parentid, pname = group.pname, company = group.company))

}


object DingtalkService {

  def companyNum(c: String) = c match {
    case "wuyang" => 101
    case "rihua" => 104
    case "lidun" => 201
    case _ => 100
  }

  def getCompanyName(n:Int) = n match {
    case 101 => "五羊"
    case 104 => "日化"
    case 201 => "礼顿"
    case _ => "集团"

  }


}
